package com.yaoyong.codegenerator.ui;

import com.yaoyong.codegenerator.constant.DatabaseType;
import com.yaoyong.codegenerator.entity.Database;
import com.yaoyong.codegenerator.utils.DatabaseUtil;
import com.yaoyong.codegenerator.utils.DbXmlUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据库连接窗口
 *
 * @author 姚勇
 */
public class DatabaseWindow extends JFrame {
    private JComboBox dbType;
    private JTextField ip;
    private JTextField username;
    private JTextField password;
    private JTextField port;
    private JComboBox db;
    private JButton testButton;
    private JButton skipButton;

    private DatabaseUtil databaseUtil = new DatabaseUtil();

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            try {
                DatabaseWindow frame = new DatabaseWindow();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * Create the frame.
     */
    public DatabaseWindow() {
        addWindowListener(new WindowAdapter() {
            /**
             * 打开窗口的时候显示数据库类型
             * @param e
             */
            @Override
            public void windowOpened(WindowEvent e) {
                loadData(e);
            }

            /**
             * 窗口关闭中释放资源
             * @param e
             */
            @Override
            public void windowClosing(WindowEvent e) {
                releaseResource(e);
            }

            /**
             * 窗口关闭后
             * @param e
             */
            @Override
            public void windowClosed(WindowEvent e) {
                releaseResource(e);
            }
        });
        setFont(new Font("微软雅黑", Font.PLAIN, 16));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);
        setBounds(100, 100, 450, 350);
        setTitle("自制代码生成器V1.0");
        getContentPane().setLayout(null);

        JLabel label1 = new JLabel("选择数据库类型");
        label1.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        label1.setHorizontalAlignment(SwingConstants.LEFT);
        label1.setBounds(25, 20, 150, 25);
        getContentPane().add(label1);

        dbType = new JComboBox();
        dbType.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        dbType.setToolTipText("请选择数据库类型");
        dbType.setForeground(SystemColor.black);
        dbType.setBackground(SystemColor.white);
        dbType.setModel(new DefaultComboBoxModel(new String[]{"----- 请  选  择 -----"}));
        dbType.setBounds(225, 25, 180, 25);
        getContentPane().add(dbType);

        JLabel label2 = new JLabel("服务器IP 端口号");
        label2.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        label2.setHorizontalAlignment(SwingConstants.LEFT);
        label2.setBounds(25, 60, 150, 25);
        getContentPane().add(label2);

        ip = new JTextField();
        ip.setHorizontalAlignment(SwingConstants.LEFT);
        ip.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        ip.setText("127.0.0.1");
        ip.setBounds(225, 60, 120, 25);
        getContentPane().add(ip);
        ip.setColumns(10);

        JLabel label3 = new JLabel("用户名");
        label3.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        label3.setHorizontalAlignment(SwingConstants.LEFT);
        label3.setBounds(25, 100, 150, 25);
        getContentPane().add(label3);

        username = new JTextField();
        username.setText("root");
        username.setHorizontalAlignment(SwingConstants.LEFT);
        username.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        username.setBounds(225, 100, 180, 25);
        getContentPane().add(username);
        username.setColumns(10);

        JLabel label4 = new JLabel("密码");
        label4.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        label4.setHorizontalAlignment(SwingConstants.LEFT);
        label4.setBounds(25, 140, 150, 25);
        getContentPane().add(label4);

        password = new JTextField();
        password.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        password.setText("root");
        password.setHorizontalAlignment(SwingConstants.LEFT);
        password.setBounds(225, 140, 180, 25);
        getContentPane().add(password);
        password.setColumns(10);

        JLabel label5 = new JLabel("数据库");
        label5.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        label5.setHorizontalAlignment(SwingConstants.LEFT);
        label5.setBounds(25, 180, 150, 25);
        getContentPane().add(label5);

        db = new JComboBox();
        db.setToolTipText("请先点击测试连接");
        db.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        db.setForeground(SystemColor.black);
        db.setBackground(SystemColor.white);
        db.setModel(new DefaultComboBoxModel(new String[]{"--请 选 择 数 据 库--"}));
        db.setBounds(225, 180, 180, 25);
        getContentPane().add(db);

        testButton = new JButton("测试连接");
        testButton.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        testButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //点击测试连接之后开启一条线程去连接数据库
                testButtonClick(e);
            }
        });
        testButton.setBounds(25, 250, 150, 25);
        getContentPane().add(testButton);

        skipButton = new JButton("跳过");
        skipButton.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        skipButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //点击跳过
                skipButtonClick(e);
            }
        });
        skipButton.setBounds(225, 250, 180, 25);
        getContentPane().add(skipButton);

        port = new JTextField();
        port.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        port.setHorizontalAlignment(SwingConstants.LEFT);
        port.setText("3306");
        port.setBounds(355, 59, 50, 25);
        getContentPane().add(port);
        port.setColumns(10);
    }

    /**
     * 点击跳过按钮
     *
     * @param e
     */
    private void skipButtonClick(ActionEvent e) {
        if ("下一步".equals(skipButton.getText())) {
            this.skipButton.setText("运行中...");
            this.skipButton.setEnabled(false);

            try {
                Database database = this.getDatabase();
                database.setUrl(database.getUrl().replace("[dbName]",database.getName()));
                database.setTables(databaseUtil.getTables(database));
                //缓存起来 key ip:port  localhost:3306
                DatabaseUtil.dbContext.put(database.getName(), database);

                //连接成功之后开启一条线程把数据库信息写到xml文件上
                new WriteDatabase2Xml(database).start();
            } catch (SQLException ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(null, "无法连接数据库，请核对连接信息是否正确", "提示", JOptionPane.OK_OPTION);
            }

        } else {
            new CodeWindow().setVisible(true);
            setVisible(false);
        }

    }

    /**
     * 点击测试连接之后开启一条线程去连接数据库
     *
     * @param e
     */
    private void testButtonClick(ActionEvent e) {
        this.testButton.setText("连接中...");
        this.testButton.setEnabled(false);
        Database database = this.getDatabase();
        new Connect2Database(database).start();
    }

    private Database getDatabase() {
        Database database = new Database();
        //拿到数据库名字
        database.setName(this.db.getSelectedItem().toString());
        // 获取指定数据库的类型mysql oracle
        DatabaseType databaseType = DatabaseType.valueOf(this.dbType.getSelectedItem().toString());
        database.setDatabaseType(databaseType);
        String mysql_url = "jdbc:mysql://[ip]:[port]/[dbName]";
        String oracle_url = "jdbc:oracle:thin:@[ip]:[port]:xe";
        //设置url
        switch (databaseType) {
            case MYSQL:
                database.setUrl(mysql_url.replace("[ip]", this.ip.getText()).replace("[port]", this.port.getText()));
                database.setDriverClassName("com.mysql.cj.jdbc.Driver");
                break;
            case ORACLE:
                database.setUrl(oracle_url.replace("[ip]", this.ip.getText()).replace("[port]", this.port.getText()));
                database.setDriverClassName("oracle.jdbc.driver.OracleDriver");
                break;
            default:
                break;
        }
        database.setUsername(this.username.getText());
        database.setPassword(this.password.getText());
        return database;
    }

    /**
     * 释放资源
     *
     * @param e
     */
    private void releaseResource(WindowEvent e) {
        closeWindow();
        System.out.println("释放资源");
    }

    private void closeWindow() {
        dispose();
        System.exit(0);
    }

    /**
     * 把数据库类型添加到数据库类型选择框
     *
     * @param e
     */
    private void loadData(WindowEvent e) {
        //设置为null则此窗口将置于屏幕的中央
        setLocationRelativeTo(null);
        List<DatabaseType> databaseType = new ArrayList<>();
        databaseType.add(DatabaseType.MYSQL);
        databaseType.add(DatabaseType.ORACLE);
        for (DatabaseType type : databaseType) {
            this.dbType.addItem(type);
        }
    }

    /**
     * 读取数据库
     */
    class Connect2Database extends Thread {
        private Database database;

        public Connect2Database(Database database) {
            this.database = database;
        }

        @Override
        public void run() {
            try {
                //手动加载驱动,解决窗口驱动不生效问题
                Class.forName(database.getDriverClassName());
                Connection connection = DatabaseUtil.getConnection(database.getUrl().replace("[dbName]","mysql"), database.getUsername(), database.getPassword());
                List<String> catalogs = databaseUtil.showDatabases(connection);
                db.removeAllItems();
                for (String c : catalogs) {
                    db.addItem(c);
                }

                JOptionPane.showMessageDialog(null, "连接成功", "提示", JOptionPane.DEFAULT_OPTION);
                skipButton.setText("下一步");
            } catch (SQLException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, "无法连接数据库，请核对连接信息是否正确", "提示", JOptionPane.OK_OPTION);
            } catch (Exception e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, "发生错误", "错误详情请查看error.log", JOptionPane.INFORMATION_MESSAGE);

            }

            testButton.setEnabled(true);
            testButton.setText("测试连接");
        }
    }

    /**
     * 把数据库信息写入配置文件xml
     */
    class WriteDatabase2Xml extends Thread {
        private Database database;

        public WriteDatabase2Xml(Database database) {
            this.database = database;
        }

        @Override
        public void run() {

            try {
                //写配置文件	把数据库信息写到xml文件上
                DbXmlUtil.write(database);

                CodeWindow codeWindow = new CodeWindow();
                codeWindow.setVisible(true);
                codeWindow.showWindowInfo(database);
                setVisible(false);
            } catch (IOException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, "IO操作异常，请核对路径是否正确", "提示", JOptionPane.ERROR_MESSAGE);
            } catch (Exception e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, "发生错误", "错误详情请查看error.log", JOptionPane.INFORMATION_MESSAGE);
            }


        }
    }

}
